package com.hsjk.szwj.module.pay.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hsjk.szwj.framework.common.constant.CommonConstant;
import com.hsjk.szwj.module.pay.dal.dataobject.config.IsvConfigContext;
import com.hsjk.szwj.module.pay.dal.dataobject.config.IsvParams;
import com.hsjk.szwj.module.pay.dal.dataobject.config.IsvsubMchParams;
import com.hsjk.szwj.module.pay.dal.dataobject.config.MchAppConfigContext;
import com.hsjk.szwj.module.pay.dal.dataobject.config.MchInfoConfigContext;
import com.hsjk.szwj.module.pay.dal.dataobject.config.NormalMchParams;
import com.hsjk.szwj.module.pay.dal.dataobject.config.WxServiceWrapper;
import com.hsjk.szwj.module.pay.dal.dataobject.config.WxpayIsvParams;
import com.hsjk.szwj.module.pay.dal.dataobject.config.WxpayNormalMchParams;
import com.hsjk.szwj.module.pay.dal.dataobject.system.IsvInfoDO;
import com.hsjk.szwj.module.pay.dal.dataobject.system.MchAppDO;
import com.hsjk.szwj.module.pay.dal.dataobject.system.MchInfoDO;
import com.hsjk.szwj.module.pay.dal.dataobject.system.PayInterfaceConfigDO;
import com.hsjk.szwj.module.pay.enums.IfCodeEnum;
import com.hsjk.szwj.module.pay.enums.MchInfoTypeEnum;
import com.hsjk.szwj.module.pay.enums.MchTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author chenjiawei
 * @desc 商户/服务商 配置信息上下文服务
 * @Date 2023/08/20 22:11
 **/
@Slf4j
@Service
public class ConfigContextService {
    /**
     * <商户ID, 商户配置项>
     **/
    private static final Map<Long, MchInfoConfigContext> mchInfoConfigContextMap = new ConcurrentHashMap<>();

    /**
     * <应用ID, 商户配置上下文>
     **/
    private static final Map<Long, MchAppConfigContext> mchAppConfigContextMap = new ConcurrentHashMap<>();

    /**
     * <服务商号, 服务商配置上下文>
     **/
    private static final Map<Long, IsvConfigContext> isvConfigContextMap = new ConcurrentHashMap<>();

    @Resource
    private IMchInfoService mchInfoService;
    @Resource
    private IMchAppService mchAppService;
    @Resource
    private IIsvInfoService isvInfoService;
    @Resource
    private PayInterfaceConfigService payInterfaceConfigService;
    @Resource
    private PayInterfaceDefineService payInterfaceDefineService;


    /**
     * 获取 [商户配置信息]
     **/
    public MchInfoConfigContext getMchInfoConfigContext(Long mchId) {

        MchInfoConfigContext mchInfoConfigContext = mchInfoConfigContextMap.get(mchId);

        //无此数据， 需要初始化
        if (mchInfoConfigContext == null) {
            initMchInfoConfigContext(mchId);
        }

        return mchInfoConfigContextMap.get(mchId);
    }

    /**
     * 获取 [商户应用支付参数配置信息]
     **/
    public MchAppConfigContext getMchAppConfigContext(Long mchId, Long appId) {

        MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(appId);

        //无此数据， 需要初始化
        if (mchAppConfigContext == null) {
            initMchAppConfigContext(mchId, appId);
        }

        return mchAppConfigContextMap.get(appId);
    }

    /**
     * 获取 [ISV支付参数配置信息]
     **/
    public IsvConfigContext getIsvConfigContext(Long isvId) {

        IsvConfigContext isvConfigContext = isvConfigContextMap.get(isvId);

        //无此数据， 需要初始化
        if (isvConfigContext == null) {
            initIsvConfigContext(isvId);
        }

        return isvConfigContextMap.get(isvId);
    }


    /**
     * 初始化 [商户配置信息]
     **/
    public synchronized void initMchInfoConfigContext(Long mchId) {
// 当前系统不进行缓存
        if (!isCache()) {
            return;
        }
        //商户主体信息
        MchInfoDO mchInfo = mchInfoService.getMchInfoById(mchId);
        // 查询不到商户主体， 可能已经删除
        if (mchInfo == null) {

            MchInfoConfigContext mchInfoConfigContext = mchInfoConfigContextMap.get(mchId);

            // 删除所有的商户应用
            if (mchInfoConfigContext != null) {
                mchInfoConfigContext.getAppMap().forEach((k, v)
                        -> mchAppConfigContextMap.remove(k));
            }

            mchInfoConfigContextMap.remove(mchId);
            return;
        }

        MchInfoConfigContext mchInfoConfigContext = new MchInfoConfigContext();

        // 设置商户信息
        mchInfoConfigContext.setMchId(mchInfo.getId());
        mchInfoConfigContext.setMchType(mchInfo.getMchType());
        mchInfoConfigContext.setMchInfo(mchInfo);
        mchAppService.list(new LambdaQueryWrapper<MchAppDO>()
                .eq(MchAppDO::getMchId, mchInfo.getId()))
                .stream().forEach(mchApp -> {

            //1. 更新商户内appId集合
            mchInfoConfigContext.putMchApp(mchApp);

            MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap
                    .get(mchApp.getId());
            if (mchAppConfigContext != null) {
                mchAppConfigContext.setMchApp(mchApp);
                mchAppConfigContext.setMchId(mchInfo.getId());
                mchAppConfigContext.setMchType(mchInfo.getMchType());
                mchAppConfigContext.setMchInfo(mchInfo);
            }
        });

        mchInfoConfigContextMap.put(mchId, mchInfoConfigContext);
    }

    /**
     * 初始化 [商户应用支付参数配置信息]
     **/
    public synchronized void initMchAppConfigContext(Long mchId, Long appId) {
// 当前系统不进行缓存
        if (!isCache()) {
            return;
        }

        // 获取商户的配置信息
        MchInfoConfigContext mchInfoConfigContext = getMchInfoConfigContext(mchId);
        // 商户信息不存在
        if (mchInfoConfigContext == null) {
            return;
        }

        // 查询商户应用信息主体
        MchAppDO dbMchApp = mchAppService.getById(appId);
        MchInfoDO mchInfoByNo = mchInfoService.getMchInfoById(mchId);

        //DB已经删除
        if (dbMchApp == null) {
            //清除缓存信息
            mchAppConfigContextMap.remove(appId);
            //清除主体信息中的appId
            mchInfoConfigContext.getAppMap().remove(appId);
            return;
        }


        // 商户应用mchNo 与参数不匹配
        if (!dbMchApp.getMchId().equals(mchInfoByNo.getId())) {
            return;
        }

        //更新商户信息主体中的商户应用
        mchInfoConfigContext.putMchApp(dbMchApp);

        //商户主体信息
        MchInfoDO mchInfo = mchInfoConfigContext.getMchInfo();
        MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();

        // 设置商户信息
        mchAppConfigContext.setAppId(appId);
        mchAppConfigContext.setMchId(mchInfo.getId());
        mchAppConfigContext.setMchType(mchInfo.getMchType());
        mchAppConfigContext.setMchInfo(mchInfo);
        mchAppConfigContext.setMchApp(dbMchApp);

        // 查询商户的所有支持的参数配置
        List<PayInterfaceConfigDO> allConfigList = payInterfaceConfigService.list(
                new LambdaQueryWrapper<PayInterfaceConfigDO>()
                        .select(PayInterfaceConfigDO::getIfId, PayInterfaceConfigDO::getIfParams)
                        .eq(PayInterfaceConfigDO::getState, CommonConstant.YES)
                        .eq(PayInterfaceConfigDO::getInfoType, MchInfoTypeEnum.APP.getType())
                        .eq(PayInterfaceConfigDO::getInfoId, appId)
        );
        // 普通商户
        if (mchInfo.getMchType().equals(MchTypeEnum.NORMAL.getValue())) {

            for (PayInterfaceConfigDO payInterfaceConfig : allConfigList) {
                String ifCode = payInterfaceDefineService.getCodeById(payInterfaceConfig.getIfId());
                mchAppConfigContext.getNormalMchParamsMap().put(
                        payInterfaceConfig.getIfId(),
                        NormalMchParams.factory(ifCode,
                                payInterfaceConfig.getIfParams())
                );
            }

            //放置 wxJavaService
            Long ifId
                    = payInterfaceDefineService.getIdByCode(IfCodeEnum.WXPAY.getCode());
            WxpayNormalMchParams wxpayParams =
                    mchAppConfigContext.getNormalMchParamsByIfId(ifId,
                            WxpayNormalMchParams.class);
            if (wxpayParams != null) {
                mchAppConfigContext.setWxServiceWrapper(WxServiceWrapper
                        .buildWxServiceWrapper(wxpayParams));
            }

        } else {
            //服务商模式商户

            for (PayInterfaceConfigDO payInterfaceConfig : allConfigList) {
                mchAppConfigContext.getIsvsubMchParamsMap().put(
                        payInterfaceConfig.getIfId(),
                        IsvsubMchParams.factory(payInterfaceDefineService.getCodeById(payInterfaceConfig.getIfId()),
                                payInterfaceConfig.getIfParams())
                );
            }
            IsvInfoDO isvInfo = isvInfoService.getIsvInfoById(mchInfo.getIsvId());
            //放置 当前商户的 服务商信息
            mchAppConfigContext.setIsvConfigContext(getIsvConfigContext(isvInfo.getId()));

        }

        mchAppConfigContextMap.put(appId, mchAppConfigContext);
    }


    /**
     * 初始化 [ISV支付参数配置信息]
     **/
    public synchronized void initIsvConfigContext(Long isvId) {
// 当前系统不进行缓存
        if (!isCache()) {
            return;
        }

        //查询出所有商户的配置信息并更新
        List<Long> mchIdList = new ArrayList<>();
        mchInfoService.list(new LambdaQueryWrapper<MchInfoDO>()
                .select(MchInfoDO::getMchNo)
                .eq(MchInfoDO::getIsvId, isvId))
                .forEach(r -> mchIdList.add(r.getId()));


        // 查询出所有 所属当前服务商的所有应用集合
        List<Long> mchAppIdList = new ArrayList<>();
        if (!mchIdList.isEmpty()) {
            mchAppService.list(new LambdaQueryWrapper<MchAppDO>()
                    .select(MchAppDO::getId)
                    .in(MchAppDO::getMchId, mchIdList))
                    .forEach(r -> mchAppIdList.add(r.getId()));
        }

        IsvConfigContext isvConfigContext = new IsvConfigContext();
        IsvInfoDO isvInfo = isvInfoService.getIsvInfoById(isvId);
        if (isvInfo == null) {

            for (Long appId : mchAppIdList) {
                //将更新已存在缓存的商户配置信息 （每个商户下存储的为同一个 服务商配置的对象指针）
                MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(appId);
                if (mchAppConfigContext != null) {
                    mchAppConfigContext.setIsvConfigContext(null);
                }
            }
            // 服务商有商户不可删除， 此处不再更新商户下的配置信息
            isvConfigContextMap.remove(isvId);
            return;
        }

        // 设置商户信息
        isvConfigContext.setIsvId(isvInfo.getId());
        isvConfigContext.setIsvInfo(isvInfo);

        // 查询商户的所有支持的参数配置
        List<PayInterfaceConfigDO> allConfigList =
                payInterfaceConfigService.list(new LambdaQueryWrapper<PayInterfaceConfigDO>()
                        .select(PayInterfaceConfigDO::getIfId, PayInterfaceConfigDO::getIfParams)
                        .eq(PayInterfaceConfigDO::getState, CommonConstant.YES)
                        .eq(PayInterfaceConfigDO::getInfoType, MchInfoTypeEnum.ISV.getType())
                        .eq(PayInterfaceConfigDO::getInfoId, isvInfo.getIsvNo())
                );

        for (PayInterfaceConfigDO payInterfaceConfig : allConfigList) {
            isvConfigContext.getIsvParamsMap().put(
                    payInterfaceConfig.getIfId(),
                    IsvParams.factory(payInterfaceDefineService.getCodeById(payInterfaceConfig.getIfId()),
                            payInterfaceConfig.getIfParams())
            );
        }

        //放置 wxJavaService
        Long ifId
                = payInterfaceDefineService.getIdByCode(IfCodeEnum.WXPAY.getCode());
        WxpayIsvParams wxpayParams = isvConfigContext
                .getIsvParamsByIfId(ifId, WxpayIsvParams.class);
        if (wxpayParams != null) {
            isvConfigContext.setWxServiceWrapper(
                    WxServiceWrapper.buildWxServiceWrapper(wxpayParams));
        }

        isvConfigContextMap.put(isvInfo.getId(), isvConfigContext);

        //查询出所有商户的配置信息并更新
        for (Long appId : mchAppIdList) {
            //将更新已存在缓存的商户配置信息 （每个商户下存储的为同一个 服务商配置的对象指针）
            MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(appId);
            if (mchAppConfigContext != null) {
                mchAppConfigContext.setIsvConfigContext(isvConfigContext);
            }
        }
    }

    private boolean isCache() {
        return false;
    }
}
